home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / CNews / Source / input / newsspool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-04  |  5.9 KB  |  302 lines

  1. /*
  2.  * newsspool - copy incoming news into incoming directory
  3.  *
  4.  * The -i option relies on the parent setting (and exporting) $PATH.
  5.  *
  6.  * -Log-
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include "fixerrno.h"
  15. #include "libc.h"
  16. #include "news.h"
  17. #include "config.h"
  18.  
  19. #ifndef lint
  20. static char RCSid[] = "$Header$";
  21. #endif
  22.  
  23. #ifndef MAXTRIES
  24. #define    MAXTRIES    100    /* limit on attempts to make links */
  25. #endif
  26.  
  27. int debug = 0;
  28. char *progname;
  29.  
  30. extern void error(), exit();
  31. #ifdef UTZOOERR
  32. extern char *mkprogname();
  33. #else
  34. #define    mkprogname(a)    (a)
  35. #endif
  36.  
  37. char buf[BUFSIZ*16];    /* try to get a batch in a few gulps */
  38. int immed = 0;        /* try an immediate newsrun? */
  39. char *suffix = ".t";    /* suffix for filename, default is plain text */
  40. char grade[3] = "";    /* 3 = digit, period, NUL */
  41.  
  42. void process();
  43. FILE *outopen();
  44. void outclose();
  45. extern time_t time();
  46. char *outname();
  47.  
  48. /*
  49.  - main - parse arguments and handle options
  50.  */
  51. main(argc, argv)
  52. int argc;
  53. char *argv[];
  54. {
  55.     int c;
  56.     int errflg = 0;
  57.     FILE *in;
  58.     struct stat statbuf;
  59.     extern int optind;
  60.     extern char *optarg;
  61.     extern FILE *efopen();
  62.     void process();
  63.  
  64.     progname = mkprogname(argv[0]);
  65.  
  66.     while ((c = getopt(argc, argv, "ig:d")) != EOF)
  67.         switch (c) {
  68.         case 'i':    /* try immediate newsrun */
  69.             immed++;
  70.             break;
  71.         case 'g':    /* grade */
  72.             if (strchr("0123456789", *optarg) == NULL)
  73.                 error("invalid grade `%s'", optarg);
  74.             sprintf(grade, "%c.", *optarg);
  75.             break;
  76.         case 'd':    /* Debugging. */
  77.             debug++;
  78.             setbuf(stderr, (char *)NULL);
  79.             break;
  80.         case '?':
  81.         default:
  82.             errflg++;
  83.             break;
  84.         }
  85.     if (errflg) {
  86.         fprintf(stderr, "usage: %s [file] ...\n", progname);
  87.         exit(2);
  88.     }
  89.  
  90.     /* probe to get unprivileged() called if necessary */
  91.     (void) ctlfile((char *)NULL);
  92.  
  93.     /* mktemp() uses access(2) [ARGH!] so minimize chances of trouble */
  94.     (void) setgid(getegid());
  95.     (void) setuid(geteuid());
  96.  
  97.     (void) umask(newsumask());
  98.  
  99.     if (optind >= argc)
  100.         process(stdin, "stdin");
  101.     else
  102.         for (; optind < argc; optind++)
  103.             if (STREQ(argv[optind], "-"))
  104.                 process(stdin, "-");
  105.             else {
  106.                 in = efopen(argv[optind], "r");
  107.                 if (fstat(fileno(in), &statbuf) < 0)
  108.                     error("can't fstat `%s'", argv[optind]);
  109.                 process(in, argv[optind]);
  110.                 (void) fclose(in);
  111.             }
  112.  
  113.     if (immed) {
  114.         /* execlp because shell files may not be directly execable */
  115.         execlp(binfile("input/newsrun"), "newsrun", (char *)NULL);
  116.         error("attempt to run newsrun failed!", "");
  117.     }
  118.     exit(0);
  119. }
  120.  
  121. /*
  122.  * process - process input file
  123.  */
  124. /* ARGSUSED */
  125. void
  126. process(in, inname)
  127. FILE *in;
  128. char *inname;
  129. {
  130.     register int count;
  131.     register int firstblock;
  132.     FILE *out;
  133.     register char *p;
  134.     register int n;
  135.     char *name;
  136.     register int wrotesome = 0;
  137.  
  138.     name = outname();
  139.     out = outopen(name);
  140.  
  141.     /* do the copying */
  142.     firstblock = 1;
  143.     while ((count = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
  144.         if (firstblock) {
  145.             n = cunskip(buf, count);
  146.             p = buf + n;
  147.             count -= n;
  148.             firstblock = 0;
  149.         } else
  150.             p = buf;
  151.         if (count > 0) {
  152.             n = fwrite(p, sizeof(char), count, out);
  153.             if (n != count)
  154.                 error("write error in output to `%s'", name);
  155.             wrotesome = 1;
  156.         }
  157.     }
  158.  
  159.     outclose(out, name, wrotesome);
  160. }
  161.  
  162. /*
  163.  - outname - construct name for the temporary output file
  164.  */
  165. char *
  166. outname()
  167. {
  168.     register char *p;
  169.  
  170.     p = strsave(fullartfile("in.coming/nspool.XXXXXX"));
  171.     mktemp(p);
  172.     return(p);
  173. }
  174.  
  175. /*
  176.  - outopen - acquire an output file
  177.  */
  178. FILE *
  179. outopen(name)
  180. char *name;
  181. {
  182.     FILE *f;
  183.  
  184.     f = fopen(name, "w");
  185.     if (f == NULL)
  186.         error("unable to create temporary `%s'", name);
  187.     if (debug)
  188.         fprintf(stderr, "output into %s\n", name);
  189.  
  190.     return(f);
  191. }
  192.  
  193. /*
  194.  - outclose - close output file, moving it to the right place
  195.  *
  196.  * Names are based on the current time in hopes of keeping input in order.
  197.  */
  198. void
  199. outclose(f, tmpname, wrotesome)
  200. FILE *f;
  201. char *tmpname;
  202. int wrotesome;            /* did anything actually get written to it? */
  203. {
  204.     register char *p;
  205.     register char *name;
  206.     register int ntries;
  207.     time_t now;
  208.  
  209.     if (nfclose(f) == EOF)
  210.         error("close error on file `%s'", tmpname);
  211.     if (!wrotesome) {
  212.         (void) unlink(tmpname);
  213.         return;
  214.     }
  215.  
  216.     if (!mkinperm(tmpname, grade, suffix))
  217.         error("couldn't move %s into the in.coming queue", tmpname);
  218.     if (debug)
  219.         fprintf(stderr, "succeeded\n");
  220. }
  221.  
  222. /*
  223.  - cunskip - inspect block for silly #! cunbatch headers, classify input
  224.  */
  225. int                /* number of chars at start to skip */
  226. cunskip(bufp, count)
  227. char *bufp;
  228. int count;
  229. {
  230.     static char goop[] = "cunbatch";
  231. #    define    GOOPLEN    (sizeof(goop)-1)    /* strlen(goop) */
  232.     static char suf[] = ".Z";
  233.     static char goop7[] = "c7unbatch";
  234. #    define    GOOP7LEN    (sizeof(goop7)-1)    /* strlen(goop7) */
  235.     static char suf7[] = ".7";
  236.     static char comp[] = "\037\235";    /* compress's magic no. */
  237.     register char *p;
  238.     register int nleft;
  239. #    define    MINCBATCH    5        /* one character, compressed */
  240.  
  241.     nleft = count;
  242.     p = bufp;
  243.  
  244.     if (nleft < 2)                /* no room for a header */
  245.         return(0);
  246.  
  247.     if (p[0] == comp[0] && p[1] == comp[1]) {    /* compressed */
  248.         if (nleft < MINCBATCH)
  249.             return(count);
  250.         suffix = suf;
  251.         return(0);
  252.     }
  253.  
  254.     if (*p++ != '#' || *p++ != '!')        /* doesn't start with #! */
  255.         return(0);
  256.     nleft -= 2;
  257.  
  258.     /* skip space */
  259.     while (nleft > 0 && (*p == ' ' || *p == '\t')) {
  260.         p++;
  261.         nleft--;
  262.     }
  263.  
  264.     /* recognize headers (the +1s ensure room for the newline) */
  265.     if (nleft >= GOOPLEN+1 && STREQN(p, goop, GOOPLEN)) {
  266.         p += GOOPLEN;
  267.         nleft -= GOOPLEN;
  268.         suffix = suf;
  269.     } else if (nleft >= GOOP7LEN+1 && STREQN(p, goop7, GOOP7LEN)) {
  270.         p += GOOP7LEN;
  271.         nleft -= GOOP7LEN;
  272.         suffix = suf7;
  273.     } else                    /* no header */
  274.         return(0);
  275.  
  276.     /* skip more space */
  277.     while (nleft > 0 && (*p == ' ' || *p == '\t')) {
  278.         p++;
  279.         nleft--;
  280.     }
  281.  
  282.     if (nleft == 0 || *p++ != '\n')        /* didn't end properly */
  283.         return(0);
  284.  
  285.     if (nleft < MINCBATCH)            /* null batch */
  286.         return(count);
  287.     return(p - bufp);
  288. }
  289.  
  290. /*
  291.  - unprivileged - drop setuidness if configuration is overridden
  292.  */
  293. void
  294. unprivileged(reason)
  295. char *reason;
  296. {
  297.     setgid(getgid());
  298.     setuid(getuid());
  299.     fprintf(stderr, "%s: renouncing setuid due to nonstandard `%s' in environment\n",
  300.                             progname, reason);
  301. }
  302.